home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / doc / prefix.ms < prev    next >
Encoding:
Text File  |  1989-11-15  |  22.8 KB  |  545 lines

  1. '\"
  2. '\" This file contains documentation for the prefix daemon
  3. '\"
  4. '\" $Id: prefix.ms,v 1.1 89/07/10 03:46:17 adam Exp $
  5. '\"
  6. '\"
  7. '\" xH is a macro to provide numbered headers that are automatically stuffed
  8. '\" into a table-of-contents, properly indented, etc. If the first argument
  9. '\" is numeric, it is taken as the depth for numbering (as for .NH), else
  10. '\" the default (1) is assumed.
  11. '\"
  12. '\" @P The initial paragraph distance.
  13. '\" @Q The piece of section number to increment (or 0 if none given)
  14. '\" @R Section header.
  15. '\" @S Indent for toc entry
  16. '\" @T Argument to NH (can't use @Q b/c giving 0 to NH resets the counter)
  17. .de xH
  18. .nr @Q 0
  19. .ds @T
  20. '\" This stuff exercises a bug in nroff. It used to read
  21. '\" .ie \\$1, but if $1 was non-numeric, nroff would process the
  22. '\" commands after the first in the true body, as well as the
  23. '\" false body. Why, I don't know. The bit with @U is a kludge, and
  24. '\" the initial assignment of 0 is necessary
  25. .nr @U 0
  26. .nr @U \\$1
  27. .ie \\n(@U>0  \{\
  28. .    nr @Q \\$1
  29. .    ds @T \\$1
  30. .    ds @R \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  31. '\}
  32. .el .ds @R \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  33. .nr @S (\\n(@Q-1)*5
  34. .nr @P \\n(PD
  35. .ie \\n(@S==-5 .nr @S 0
  36. .el .nr PD 0
  37. .NH \\*(@T
  38. \\*(@R
  39. .XS \\n(PN \\n(@S
  40. \\*(SN \\*(@R
  41. .XE
  42. .nr PD \\n(@P
  43. ..
  44. '\" CW is used to place a string in fixed-width or switch to a
  45. '\" fixed-width font.
  46. '\" C is a typewriter font for a laserwriter. Use something else if
  47. '\" you don't have one...
  48. .de CW
  49. .ie !\\n(.$ .ft C
  50. .el \&\\$3\fC\\$1\fP\\$2
  51. ..
  52. '\" Anything I put in a display I want to be in fixed-width
  53. .am DS
  54. .CW
  55. ..
  56. .de Bp
  57. .ie !\\n(.$ .IP \(bu 2
  58. .el .IP "\&" 2
  59. ..
  60. .po +.3i
  61. .RP
  62. .TL
  63. Prefix \*- Painless Filesystem Management
  64. .AU
  65. Adam de Boor
  66. .AI
  67. Berkeley Softworks
  68. 2150 Shattuck Ave, Penthouse
  69. Berkeley, CA 94704
  70. adam@bsw.uu.net
  71. \&...!uunet!bsw!adam
  72. .AB
  73. .FS "\&
  74. \(co Copyright Adam de Boor and Berkeley Softworks, 1989.
  75. Permission to use, copy, modify, and distribute this software and its
  76. documentation for any purpose and without fee is hereby granted,
  77. provided that the above copyright notice appears in all copies.
  78. Neither Berkeley Softworks, nor Adam de Boor makes any
  79. representations about the suitability of this software for any
  80. purpose.  It is provided "as is" without express or implied warranty.
  81. .FE
  82. This paper describes the installation, use and theory of operation of
  83. .CW prefix ,
  84. a simple daemon to implement a ``prefix table'' for
  85. .UX
  86. using NFS\(tm. The daemon provides for a less painful filesystem
  87. management scheme than the current static configuration file and mount
  88. table scheme, allowing for the dynamic mounting, location and unmounting of
  89. filesystems according to user demand. The intent of the daemon is to
  90. provide a globally consistent filesystem for use with PMake and Customs.
  91. .AE
  92. .nr PD .1i
  93. '\"
  94. '\"        INTRODUCTION
  95. '\"
  96. .xH Introduction
  97. .LP
  98. The ``prefix'' program implements a ``prefix table'' for
  99. .UX
  100. running NFS. ``What's a prefix table?'' you ask. A prefix table is a
  101. less administration-intensive way of maintaining network filesystems,
  102. relying on the network to provide the location of a particular
  103. filesystem, rather than a static configuration file (/etc/fstab) as is
  104. done now. In addition, the set of mounted systems is dynamic, with
  105. unneeded systems automatically unmounted and mounted again when
  106. necessary. This dynamic configuration helps to reduce the chances of a
  107. client hanging because the server of some unneeded filesystem has gone down.
  108. .LP
  109. The implementation revolves around the notion of a ``prefix'' \*- a
  110. unique name for a particular filesystem that is common across all
  111. systems on the local network. The ``prefix'' daemon controls access to
  112. these prefixes. When a client wishes to access a file in a prefixed
  113. filesystem, the daemon broadcasts to the local network to find out
  114. what machine is currently serving the prefix, accepting the first
  115. responder as the machine whose proferred filesystem it will use. This
  116. allows a prefix to be served by more than one host, with the one most
  117. able to serve the prefix (i.e. the one that can respond the fastest)
  118. being the one chosen. After determining the server of the prefix, the
  119. daemon mounts the appropriate filesystem from the server and the
  120. client's request passes on to the server to be handled.
  121. .LP
  122. It is important to note that this daemon does
  123. .B not
  124. bypass the normal access controls provided by NFS. While anyone can
  125. tell the local prefix daemon that a particular directory is to be
  126. exported under a given prefix, this doesn't preclude the local mount
  127. daemon from refusing access based on the /etc/exports file.
  128. .LP
  129. While there were several goals considered in the writing of this
  130. daemon, the primary one was the providing of a globally consistent
  131. filesystem across all client machines to allow PMake and Customs to
  132. operate without concern. That it is also helpful for users and
  133. administrators in general is a pleasant by-product. Because of this
  134. goal, and the fairly trusting atmosphere already assumed by Customs,
  135. the service is not as elaborate as it might be, though I doubt not
  136. that it will evolve over time as it is used in more diverse environments.
  137. .LP
  138. ``prefix'' was inspired by the
  139. .CW automount
  140. program that comes with the latest Sun OS 4.0 release (4.0.3). It
  141. operates rather differently, however, in that automounted filesystems
  142. are mounted \fIin place\fP, rather than under some temporary mount
  143. directory. This is required by PMake's need for a globally consistent
  144. filesystem. The problem lies in the
  145. .CW getwd
  146. library function. If the directory
  147. .CW /n/promethium
  148. were mounted on
  149. .CW /tmp_mnt/n/promethium ,
  150. as automount would like, getwd would return a path within the /tmp_mnt
  151. directory. This is ok, as far as local work goes, since /tmp_mnt is in
  152. fact where the files are to be found. Unfortunately, if PMake exports
  153. a job somewhere, it will pass along this path to the remote job and
  154. Customs will attempt to change to that directory, an attempt that will
  155. fail unless someone on the remote machine has also caused the
  156. file system to be automounted. With ``prefix,'' however, the file
  157. system will always be in the same place, or will be automounted if it
  158. is not, and getwd will return the proper value.
  159. '\"
  160. '\"        OPERATION
  161. '\"
  162. .xH Operation
  163. .LP
  164. The prefix daemon has two jobs to perform:
  165. .RS
  166. .Bp
  167. Export prefixes to other machines, providing the local directory name
  168. in response to a request from a remote prefix daemon.
  169. .Bp
  170. Import prefixes from other machines, locating their servers and
  171. mounting them for normal NFS access on demand, unmounting them when
  172. they are no longer required.
  173. .RE
  174. .LP
  175. The first task is simple to perform and quickly explained. Any
  176. directory on the system may be declared to be the server for a prefix.
  177. When a request arrives for the given prefix, the daemon will respond
  178. with the directory. To ensure against ``operator error,'' prefix will consult
  179. .CW /etc/exports
  180. to make sure the directory is actually exported, warning you if it
  181. can't locate the directory. Note that no attention is paid to the
  182. export restrictions that may be placed in the file. This is arguably a
  183. bug, as it could cause a remote system to fail in mounting a prefix
  184. that it could actually get from somewhere else simply because the
  185. restricted host responded first.
  186. .LP
  187. Imported prefixes are divided into two categories: ``root'' and
  188. ``imported'' prefixes.
  189. .LP
  190. An ``imported'' prefix is a real prefix available on the network. As
  191. such, prefix will broadcast for the prefix's server whenever you try
  192. to lookup anything in that directory.
  193. .LP
  194. A ``root'' prefix, on the other hand, is internal to the machine,
  195. being the root of a tree of prefixes. Anything sought by the kernel
  196. immediately below one is assumed to be an imported prefix, to be sought
  197. on the network should the kernel attempt to locate anything inside it.
  198. For example, if you have a network of machines with local disks and
  199. you want the main partition of each to be accessible as
  200. .CW /n/ \fImachine\fP,
  201. declaring
  202. .CW /n
  203. to be a root prefix will cause the proper thing to happen.
  204. .LP
  205. Why this difference? It's more flexible, since prefix must be informed
  206. of each prefix it should import (not being party to the name lookup
  207. performed by the kernel). It is much easier to have a few, well-known
  208. root prefixes under which needed directories can be exported than to
  209. have each prefix entered in a configuration file on each client
  210. system. One of the purposes of this daemon is, after all, to get away
  211. from a static configuration file.
  212. '\"
  213. '\"        OPTIONS
  214. '\"
  215. .xH Options
  216. .LP
  217. ``prefix'' accepts several command-line options that dictate its actions:
  218. .IP "\-D[D]                  "
  219. Enter daemon mode. This includes detaching from its parent. If the
  220. second D is given, prefix will enter its debugging mode.
  221. .IP "\-d \fIprefix\fP        "
  222. Causes the imported or exported prefix to be deleted. If the prefix is
  223. imported and mounted, it will be unmounted first. If the prefix is a
  224. root prefix, all mounted subprefixes will be unmounted first. If any
  225. unmounting fails, the prefix will not be deleted.
  226. .IP "\-f \fIfile\fP          "
  227. Specifies a configuration file to be read. If the file is read
  228. successfully, this automatically implies \-D.
  229. .IP "\-i \fIprefix\fP        "
  230. Import the given prefix, using the default mounting options (rw).
  231. .IP "\-p                     "
  232. Print the current state of imported and exported prefixes.
  233. .IP "\-q                     "
  234. Used only when invoking prefix as a daemon, causes standard status messages
  235. not to be sent to the console. Error messages are still written there, however.
  236. .IP "\-r \fIprefix\fP        "
  237. Set the given prefix as a root prefix.
  238. .IP "\-x \fIdirectory\fP [\fIprefix\fP]"
  239. Export the given directory under the given prefix, or as itself if no
  240. prefix given. If \fIdirectory\fP doesn't appear in
  241. .CW /etc/exports ,
  242. a warning message is printed to the console.
  243. '\"
  244. '\"        INSTALLATION
  245. '\"
  246. .xH Installation
  247. .LP
  248. The installation of ``prefix'' is relatively simple, since it is a
  249. more-or-less self-contained system. The program operates in either
  250. daemon mode or as a user's agent when conversing with the local
  251. daemon, so it should probably be installed in /etc with a link to it
  252. from a user-accessible directory. 
  253. .ul
  254. It should not be setuid to root.
  255. As it must be started at boot time, when it will be executed by root,
  256. there is no need to make it setuid.
  257. .LP
  258. Examine the makefile in the prefix directory to set the installation
  259. point and the directory in which the symbolic link is to be placed, as
  260. well as to set the names of certain system files, if you've moved
  261. them. You should then be able, as root, to type ``make install''.
  262. .LP
  263. Once you've installed the daemon, you must arrange for it to start at
  264. boot time and be given the proper set of initial prefixes, both imported
  265. and exported. The best way to tell it this information is via a
  266. (short) configuration file. I use
  267. .CW /etc/prefix.conf .
  268. The configuration file consists of a series of command lines, with
  269. optional comments interspersed. There are five commands understood:
  270. import, export, root, quiet and debug.
  271. .IP "import \fIprefix\fP [\fImount options\fP]
  272. Declares \fIprefix\fP to be an imported prefix. When it is mounted,
  273. the optional \fImount options\fP are used. These options are exactly
  274. as used in /etc/fstab and default to
  275. .CW "rw"
  276. if you don't give any.
  277. .IP "export \fIdirectory\fP [\fIprefix\fP]
  278. Declares \fIdirectory\fP to be exported under \fIprefix\fP, if given,
  279. or as itself if no prefix is specified.
  280. .IP "root \fIprefix\fP [\fImount options\fP]
  281. Declares \fIprefix\fP to be a root prefix. Any prefix mounted under it
  282. will be mounted with the given \fImount options\fP, as described for the
  283. .CW import
  284. command.
  285. .IP "quiet            "
  286. Normally, prefix will write to /dev/console when it is broadcasting
  287. for the server of a prefix, as well as what server/directory pair it is
  288. actually mounting and any problems with the mounting it encounters. If the
  289. .CW quiet
  290. command is given, the notices about the broadcasting for and the
  291. server of a prefix will not be printed. Error messages will still be
  292. written to the console, however.
  293. .IP "debug             "
  294. Turns on debugging for the daemon, including extensive heap checking
  295. and very verbose progress messages that were needed during development
  296. because the thing very frequently caused the machine to hang (thank
  297. you ``disk wait,'' may you rot in Hell). Not very useful...
  298. .LP
  299. As an example, here is the configuration file I've got on my workstation:
  300. .DS
  301. .ta \w'export    'u +\w'/old_staff    'u
  302. #
  303. # Prefix configuration file for promethium
  304. #
  305. #
  306. # Standard prefix roots
  307. #
  308. root    /n    rw,intr
  309. root    /rn    rw,intr
  310. #
  311. # Standard imports
  312. #
  313. import    /old_staff    rw,intr
  314. #
  315. # Machine-specific imports/roots
  316. #
  317. import    /usr/src    rw,intr
  318. #
  319. # Standard exports
  320. #
  321. export    /    /rn/pm
  322. export    /n/pm
  323. export    /n/pm    /n/promethium
  324. .DE
  325. .LP
  326. The mount options are optional, even though I've got them for all
  327. imported prefixes. Note also that the same disk partition (/n/pm) is
  328. exported under two names. This is perfectly acceptable.
  329. .LP
  330. One other question arises in as far as in which /etc/rc.foo file the
  331. daemon should be started. I start it in /etc/rc itself, with the command:
  332. .DS
  333. if [ -f /etc/prefix -a -f /etc/prefix.conf ]; then
  334.     (echo starting prefix daemon)                >/dev/console
  335.     /etc/prefix /etc/prefix.conf 
  336. fi
  337. .DE
  338. This goes immediately before the mounting of the remaining local (4.2
  339. or 4.3-type) partitions from /etc/fstab because I've a partition that
  340. wants mounting on
  341. .CW /n/pm .
  342. Because of the way the daemon works, and the fact that /n is a (root)
  343. prefix, the daemon must be started before the local partition is
  344. mounted, or I wouldn't be able to access the local partition (dire
  345. things would happen, likely). It is permissible to explicitly mount a local or
  346. remote filesystem immediately under a root prefix, as the prefix is
  347. only sought should you attempt to look anything up in it (mounting
  348. a filesystem doesn't qualify), nor will the kernel try and look
  349. anything up there so long as the filesystem remains mounted.
  350. .LP
  351. An alternative, albeit a strange one, to the configuration file is to
  352. specify all the prefixes using command line options.
  353. '\"
  354. '\"        INTERNALS
  355. '\"
  356. .xH Internals
  357. .LP
  358. This section is intended to give you a working understanding of how
  359. the prefix daemon does its job, so you'll have some idea of what's
  360. going on should the daemon have a bug in it (gasp! not \fImy\fP software!).
  361. .LP
  362. The main aspect of the daemon to know is that it appears to the kernel
  363. as just another NFS server. The kernel doesn't care that its address
  364. is on the local machine, as long as the daemon obeys the protocol.
  365. Prefix sets up one mount point (with itself as the server) for each
  366. imported and root prefix, with one other mount point at
  367. .CW /.prefix
  368. whose purpose I'll explain in a bit. These mount points are made
  369. \fIsoft\fP with timeout and retransmission parameters tailored to the
  370. operation of the daemon. They are soft so operations can just timeout
  371. should the daemon die (remember, this is fairly young software).
  372. .LP
  373. As a directory, each mount point should be considered (and is actually
  374. mounted) \fIread-only\fP \*- you cannot create symbolic links,
  375. subdirectories or files in one.  The only NFS operations supported are
  376. the fetching of attributes, the lookup of a file, the fetching of
  377. filesystem attributes and the reading of directory entries (always
  378. just . and .., except for a root prefix, from which a client will also
  379. obtain the names of previously encountered subprefixes).
  380. .LP
  381. For all of these mount points, save that for /.prefix, only the lookup
  382. of a file will cause the daemon to do anything special \*- fetching
  383. the attributes of an unmounted prefix will return the attributes of
  384. the underlying directory; reading it as a directory will only return
  385. precalculated information, potentially making someone erroneously
  386. think the prefix is mounted and empty, or that the daemon has died.
  387. The reason prefix waits for a lookup is to prevent the search for, and
  388. mounting of, a prefix until it is absolutely necessary \*- you
  389. wouldn't want to have the prefix mounted if the user just did an ls of
  390. its containing directory, would you? So it is when you lookup
  391. something in the prefix that the fun begins.
  392. '\"
  393. '\"            MOUNTING
  394. '\"
  395. .xH 2 Mounting \*- The Fun Begins
  396. .LP
  397. For a root prefix, the fun is short-lived: all the daemon does is
  398. create a new prefix for its own use and return a handle and the root's
  399. attributes (though with a different file number, so the kernel won't
  400. get confused).
  401. .LP
  402. For an imported prefix, however, the lookup of a file is a momentous
  403. occasion. The importance, however, is lost on the daemon, as it will
  404. always return the same answer: no matter what is being sought, prefix
  405. will always say the target is a symbolic link to something in
  406. the /.prefix directory. This subterfuge is necessary to cause the
  407. kernel to unlock the data structure by which it found the prefix
  408. daemon, allowing the daemon to unmount itself and mount the real filesystem
  409. instead.  This bait and switch is performed when the kernel, using the
  410. contents of the symbolic link the daemon returned, talks to the daemon
  411. again, asking it to look something up in its /.prefix directory.
  412. .LP
  413. The format of the link contents returned by the previous lookup
  414. operation is simply
  415. .DS
  416. /.prefix/\fIprefix\fP/\fIcomponent\fP
  417. .DE
  418. where \fIprefix\fP is the address of the daemon's internal prefix
  419. descriptor (in ascii) and \fIcomponent\fP is the component the kernel
  420. was attempting to find within the prefix. The daemon delays its search
  421. for the server of the prefix until the kernel actually attempts to
  422. read the symbolic link whose handle it returned, at which point it
  423. assumes the kernel must be serious in its desire for the prefix, so it
  424. broadcasts to the network to find the server of the prefix, recording
  425. the results until the kernel acts on the link contents.
  426. .LP
  427. When the daemon gets this second lookup request, it can be fairly
  428. certain that the prefix's mount point is free and attempts to unmount
  429. itself from it. Should this fail, the lookup request will return a
  430. general system error to the kernel, which the kernel will ignore until
  431. it's been told enough times (this is why the broadcast for the
  432. prefix's server is done when the link is read, not here, since the
  433. link read will never fail). Should the daemon not be able to
  434. disentangle itself from the prefix, the user will get back a message
  435. about a remote system error from the kernel. This rarely happens,
  436. however, so you needn't worry too much about it.
  437. .LP
  438. Once the daemon has unmounted itself, it goes through the process of
  439. mounting the remote system in its place. Again, if this fails, the
  440. user will see a message about a remote system error and the daemon
  441. will re-mount itself on the prefix so the user can try again once
  442. s/he's (or you've) straightened things out.
  443. .LP
  444. If the remote mount succeeds, the kernel is told that the component it
  445. is seeking (which will be the ascii representation of the prefix's
  446. address) is also a symbolic link, but this one's back to the prefix
  447. itself. The kernel performs the same lookup it did before, since the
  448. daemon tacked the component the kernel was seeking onto the end of the link
  449. contents it returned, but this time the request goes to the real
  450. server of the filesystem.
  451. .LP
  452. A mounted prefix is displayed in /etc/mtab in a slightly different
  453. format than usual. Rather than giving the server as
  454. ``\fIserver\fP:\fIdirectory\fP'', I have chosen to display it as
  455. ``\fIserver\fP[\fIdirectory\fP]'' in an attempt to distinguish between
  456. permanent systems people are used to and the transient systems that
  457. are prefixes.
  458. '\"
  459. '\"            UNMOUNTING
  460. '\"
  461. .xH 2 Unmounting
  462. .LP
  463. Once the prefix is mounted on a remote filesystem, the question arises
  464. of when to unmount it. The goal of reducing a machine's vulnerability
  465. to server crashes would certainly not be met if all prefixes ever
  466. referenced by a machine were to remain mounted, nor would
  467. administrators be able to switch the serving of a prefix to another
  468. machine very easily. To avoid this, prefix will attempt to unmount a
  469. mounted prefix every ten minutes or so. If the attempt is successful,
  470. the entry is removed from /etc/mtab and the daemon once again takes
  471. over the mount point.
  472. .LP
  473. This solution isn't ideal of course, as one would much prefer to
  474. unmount a prefix only ten minutes after it was last accessed, for
  475. instance, rather than whenever it's possible at a ten minute interval.
  476. Even if you've got a program referencing a prefix every five seconds,
  477. it could still be unmounted if the program is merely stat'ing a file,
  478. for example, rather than keeping a file open. To allow the daemon
  479. access to the last-access time of a prefix would either require
  480. special kernel support (stat'ing the root of the filesystem doesn't
  481. help, since the access time of the directory isn't modified when a
  482. directory search is performed; only when the directory is actually
  483. read), or it would force the daemon to act as an intermediary between
  484. the kernel and the remote server, an alternative I deemed too costly,
  485. given the extra copies required on reads and writes (for a write, the
  486. data would flow from the client to the kernel to the daemon to the
  487. kernel to the remote system, causing an extra two copies, usually of
  488. 8K each or more).
  489. '\"
  490. '\"            MISCELLANEOUS
  491. '\"
  492. .xH 2 Miscellaneous
  493. .LP
  494. The daemon actually runs as two processes, one of which services the
  495. various mount points and is generally in charge of everything. The
  496. other process performs all the mount and unmount system calls at the
  497. behest of the first process (actually, the one with the higher PID is
  498. the one that's in charge, but who's counting?).
  499. .LP
  500. The daemon needs to be in two pieces so the kernel can check out
  501. prefixes during mounting or unmounting, especially for the children of
  502. a root prefix (in order to mount the remote system on a subprefix, the
  503. kernel must request a file handle from the root prefix. Since the
  504. daemon can't run to field this request while it's in the kernel
  505. performing the mount, having only a single process would cause instant,
  506. unending deadlock).
  507. '\"
  508. '\"        QUIRKS
  509. '\"
  510. .xH Quirks
  511. .LP
  512. There are a few non-obvious pieces of behaviour exhibited by a system
  513. running this daemon. One already mentioned is the tendency to generate
  514. strange error messages should a prefix be unmountable. As an example,
  515. the command
  516. .DS
  517. cd /n/fishnet/biscuit
  518. .DE
  519. will yield the following two enlightening messages:
  520. .DS
  521. NFS readlink failed for server prefix: RPC: Remote system error
  522. /n/fishnet/biscuit: Unknown error
  523. .DE
  524. .LP
  525. Another quirk is exhibited by doing and ``ls -l'' of anything under an
  526. as-yet unmounted prefix. While the prefix will indeed be mounted by
  527. this operation, the nature of ls -l will cause output like this
  528. .DS L
  529. lrwxrwxrwx  1 root  23 Dec 31  1969 /usr/src/public -> /.prefix/164480/public
  530. .DE
  531. to be displayed, to the edification of no one.
  532. '\"
  533. '\"        EXTENSIONS
  534. '\"
  535. .xH Extensions
  536. .LP
  537. This service is by no means complete. The understanding of the access
  538. controls in /etc/exports for exported prefixes is an example of a
  539. worthwhile extension, as would an additional call to force all active
  540. prefixes to unmount a prefix, if possible, to allow an administrator
  541. to switch the server of a prefix. Unfortunately, I have little time to
  542. implement such extensions (nor do I need them at the moment).
  543. Ideas, however, are always welcome, especially if accompanied by code.
  544. .TC
  545.